package com.bprogram.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bprogram.mapper.UploadMapper;
import com.bprogram.pojo.Upload;
import com.bprogram.service.UploadService;
import com.bprogram.utils.IdGenerator;
import com.bprogram.utils.RedisUtil;
import com.qiniu.util.Auth;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.qiniu.common.QiniuException;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

import it.sauronsoftware.jave.Encoder;

import javax.annotation.Resource;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cai
 * @since 2023-11-21
 */
@Service
public class UploadServiceImpl extends ServiceImpl<UploadMapper, Upload> implements UploadService {


    @Autowired
    private Auth auth;

    @Autowired
    private UploadManager uploadManager;

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private BucketManager bucketManager;

    @Value("${OSS.path}")
    private String path;       // 域名
    @Value("${OSS.photoPath}")
    private String photoPath;   // 服务器存图片的文件夹
    @Value("${OSS.videoPath}")
    private String videoPath;   // 服务器存视频的文件夹
    @Value("${file.photo}")
    private String[] photoType; //图片允许的扩展名
    @Value("${file.video}")
    private String[] videoType; //图片允许的扩展名
    @Value("${OSS.bucketName}")
    private String bucketName;   // 存储空间

    @Override
    public String uploadFile(MultipartFile file, String type) throws RuntimeException {
        try {
            //获取原始文件名
            String originalFileName = Objects.requireNonNull(file.getOriginalFilename());
            //判断文件是否允许上传
            if (!isFileAllowed(originalFileName, type)) {
                Assert.isTrue(false, "格式错误，请检查后重新上传");
            }
            //生成文件名
            String fileName = getRandomImgName(originalFileName);
            //默认不指定key的情况下，以文件的hash值作为文件名

            byte[] uploadBytes = file.getBytes();
            String upToken = auth.uploadToken(bucketName);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            String date = simpleDateFormat.format(new Date());
            String key = null;
            if ("video".equals(type)) {
                key = videoPath + date + "/" + fileName;
                //MultipartFile转file，获取视频时长并将其保存到redis

                File file2 = new File(System.getProperty("user.dir"), key);
                FileUtils.copyInputStreamToFile(file.getInputStream(), file2);
                Encoder encoder = new Encoder();
                it.sauronsoftware.jave.MultimediaInfo m = null;
                m = encoder.getInfo(file2);
                long ls = m.getDuration();
                String duration = ls / 3600000 + ":" + (ls / 60000) % 60 + ":" + (ls / 1000) % 60 % 60;  //0:3:31
                redisUtil.hset("video",key,duration);
                file2.delete();
            } else if ("img".equals(type)) {
                key = photoPath + date + "/" + fileName;
            }
            uploadManager.put(uploadBytes, key, upToken);

            return key; //key:img/20231216/dbf8808af9224cd394ed6e4f70a39ff0.jpeg
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("错误的文件名");
        } catch (Exception e) {
            throw new RuntimeException("文件上传出错");
        }
    }

    @Override
    public Boolean deleteFile(String key) throws RuntimeException {
        if (Objects.isNull(checkFile(key))) {
            return true;
        } else {
            try {
                bucketManager.delete(bucketName, key);
                return true;
            } catch (QiniuException e) {
                throw new RuntimeException(e.getMessage());
            }
        }
    }

    @Override
    public FileInfo checkFile(String key) {
        FileInfo fileInfo = null;

        try {
            fileInfo = bucketManager.stat(bucketName, key);
        } catch (QiniuException e) {
            e.printStackTrace();
        }
        System.out.println("文件hash" + fileInfo.hash);
        System.out.println("文件size" + fileInfo.fsize);
        System.out.println("文件mimeType" + fileInfo.mimeType);
        System.out.println("文件putTime" + fileInfo.putTime);

        return fileInfo;
    }

    @Override
    public String getFileAskingPath(String filePath) {
        return path + "/" + filePath;
    }

    /**
     * 生成唯一图片名称
     *
     * @param fileName 原文件名
     * @return 云服务器fileName
     */
    private static String getRandomImgName(String fileName) throws IllegalArgumentException {
        int index = fileName.lastIndexOf(".");

        if (fileName.isEmpty() || index == -1) {
            throw new IllegalArgumentException();
        }
        // 获取文件后缀
        String suffix = fileName.substring(index).toLowerCase();
        // 生成UUID
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        // 拼接新的名称
        return uuid + suffix;
    }

    /**
     * 判断图片是否被允许上传
     *
     * @param fileName 文件名
     * @return 允许true, 否则false
     */
    private boolean isFileAllowed(String fileName, String type) {
        // 获取后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        if ("video".equals(type)) {
            for (String allow : videoType) {
                if (allow.equals(suffixName)) {
                    return true;
                }
            }
        } else if ("img".equals(type)) {
            for (String allow : photoType) {
                if (allow.equals(suffixName)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public Upload saveOrUpdateUpload(Upload upload) {
        if (StringUtils.isEmpty(upload.getFileId())) {
            IdGenerator idGenerator = new IdGenerator();
            upload.setFileId(idGenerator.snowflakeId());
            this.save(upload);
            return upload;
        }
        UpdateWrapper<Upload> wrapper = new UpdateWrapper<>();
        wrapper.eq("fileId", upload.getFileId());
        wrapper.eq("fileAssociation", upload.getFileAssociation());
        Upload uploadUpload = new Upload();
//        更改视频标题
        if (StringUtils.isEmpty(upload.getFileName())) {
            uploadUpload.setFileName(upload.getFileName());
        }
        this.update(uploadUpload, wrapper);
        return upload;
    }



    /**
     * 递归删除文件及其子文件
     *
     * @param folder
     */
    public void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    // 递归删除子文件夹及其内容
                    deleteFolder(file);
                } else {
                    // 删除文件
                    file.delete();
                }
            }
        }
        // 删除空文件夹
        folder.delete();
    }
    @Override
    public boolean delete() {
        //删除本地残余的文件
        File file = new File(System.getProperty("user.dir"), "/video");
        if (!file.exists() && !file.isDirectory()) file.mkdirs();
        deleteFolder(file);
        //删除服务器上多余的文件
        return false;
    }
}
